package com.muyu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.muyu.api.exception.BusinessException;
import com.muyu.mapper.UserQuestionsMapper;
import com.muyu.model.bo.UploadFilesBO;
import com.muyu.model.config.ReviewFileConfigDTO;
import com.muyu.model.entity.UserQuestionsEntity;
import com.muyu.service.UserQuestionsService;
import com.muyu.util.Uploader;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @ClassName: UserQuestionsServiceImpl
 * @Author: Zirun.Xin
 * @Date: 2025/4/29 下午2:29
 * @Version: 1.0
 * @Description: 问题反馈业务实现层
 */
@Service
@RequiredArgsConstructor
public class UserQuestionsServiceImpl extends ServiceImpl<UserQuestionsMapper, UserQuestionsEntity>
        implements UserQuestionsService {

    /**
     * 问题反馈持久层
     */
    private final UserQuestionsMapper userQuestionsMapper;

    /**
     * 自定义文件存放地址配置对象
     */
    private final ReviewFileConfigDTO reviewFileConfigDTO;

    /**
     * 文件/图片等上传组件
     */
    private final Uploader uploader;

    /**
     * 获取已上传过截图的问题反馈
     *
     * @return 获取数据
     */
    @Override
    public List<UserQuestionsEntity> getQuestions() {
        LambdaQueryWrapper<UserQuestionsEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.isNotNull(UserQuestionsEntity::getFilePaths);
        List<UserQuestionsEntity> userQuestionsEntityList = userQuestionsMapper.selectList(queryWrapper);
        return userQuestionsEntityList;
    }

    /**
     * 根据图片地址进行预览
     *
     * @param imgPath   图片地址
     * @param accountId 账户id
     */
    @Override
    public void reviewImgByPath(String imgPath, String accountId) {
        // 获取response
        HttpServletResponse response = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder
                .getRequestAttributes())).getResponse();

        // 拼接预览图片
        String targetPath = Paths.get(reviewFileConfigDTO.getQuestionImg(), accountId, imgPath).toString();

        try {
            uploader.previewImage(response, targetPath);
        } catch (FileNotFoundException e) {
            throw new BusinessException(1007, "文件不存在或路径错误");
        } catch (SecurityException e) {
            throw new BusinessException(1008, "没有权限访问文件");
        } catch (IOException e) {
            throw new BusinessException(1009, "文件读取/写入错误");
        }
    }

    /**
     * 根据图片地址进行下载
     *
     * @param imgPath   图片地址
     * @param accountId 账户id
     */
    @Override
    public void downloadImgByPath(String imgPath, String accountId) {
        // 获取response
        HttpServletResponse response = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder
                .getRequestAttributes())).getResponse();

        // 拼接图片下载地址
        String targetPath = Paths.get(reviewFileConfigDTO.getQuestionImg(), accountId, imgPath).toString();

        // 调用下载方法
        try {
            uploader.downloadImage(targetPath, response);
        } catch (FileNotFoundException e) {
            throw new BusinessException(1007, "文件不存在或路径错误");
        } catch (IOException e) {
            throw new BusinessException(1009, "文件读取/写入错误");
        }
    }

    /**
     * 保存用户问题及关联图片
     *
     * @param images           上传的图片文件数组
     * @param creatorName      创建者姓名
     * @param creatorAccountId 创建者账号ID
     * @param creatorDept      创建者部门
     * @param questionContent  问题内容
     * @param questionType     问题类型
     * @throws BusinessException 当参数无效、图片处理失败或数据库操作失败时抛出
     */
    @Override
    public void saveQuestion(MultipartFile[] images, String creatorName, String creatorAccountId, String creatorDept, String questionContent, String questionType) {
        // 参数校验
        validateParameters(images, creatorName, creatorAccountId, creatorDept, questionContent, questionType);

        // 处理图片上传
        List<UploadFilesBO> uploadFilesBOList = processImages(images, creatorAccountId);

        // 检查是否有有效图片
        if (uploadFilesBOList.isEmpty()) {
            throw new BusinessException(10010, "至少需要上传一张有效的JPG图片！");
        }

        // 上传所有图片
        uploadImages(uploadFilesBOList);

        // 构建并保存问题实体
        saveQuestionEntity(uploadFilesBOList, creatorName, creatorAccountId,
                creatorDept, questionContent, questionType);
    }

    /**
     * 验证方法参数是否有效
     *
     * @param images           图片文件数组
     * @param creatorName      创建者姓名
     * @param creatorAccountId 创建者账号ID
     * @param creatorDept      创建者部门
     * @param questionContent  问题内容
     * @param questionType     问题类型
     * @throws BusinessException 当任何必填参数为空时抛出
     */
    private void validateParameters(MultipartFile[] images, String creatorName, String creatorAccountId,
                                    String creatorDept, String questionContent, String questionType) {
        if (images == null || images.length == 0) {
            throw new BusinessException(10010, "图片文件不能为空！");
        }
        if (StringUtils.isAnyBlank(creatorName, creatorAccountId, creatorDept, questionContent, questionType)) {
            throw new BusinessException(10011, "必填参数不能为空！");
        }
    }

    /**
     * 处理上传的图片文件，筛选有效图片并生成存储信息
     *
     * @param images           原始图片文件数组
     * @param creatorAccountId 创建者账号ID，用于构建存储路径
     * @return 包含有效图片信息的UploadFilesBO列表
     */
    private List<UploadFilesBO> processImages(MultipartFile[] images, String creatorAccountId) {
        List<UploadFilesBO> uploadFilesBOList = new ArrayList<>();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String timestamp = dateFormat.format(new Date());

        for (int i = 0; i < images.length; i++) {
            MultipartFile image = images[i];
            if (image == null || image.isEmpty()) {
                continue;
            }

            // 获取文件后缀并验证
            String originalFilename = image.getOriginalFilename();
            if (originalFilename == null || !originalFilename.toLowerCase().endsWith(".jpg")) {
                continue;
            }

            // 构建文件名和路径
            String fileName = String.format("%s_%d.jpg", timestamp, i);
            String uploadPath = Paths.get(System.getProperty("user.dir"),
                    reviewFileConfigDTO.getQuestionImg(),
                    creatorAccountId, fileName).toString();

            uploadFilesBOList.add(UploadFilesBO.builder()
                    .file(image)
                    .targetPath(uploadPath)
                    .fileName(fileName)
                    .build());
        }
        return uploadFilesBOList;
    }

    /**
     * 上传所有有效图片到指定路径
     *
     * @param uploadFilesBOList 包含图片信息的UploadFilesBO列表
     * @throws BusinessException 当任何图片上传失败时抛出
     */
    private void uploadImages(List<UploadFilesBO> uploadFilesBOList) {
        for (UploadFilesBO uploadFilesBO : uploadFilesBOList) {
            try {
                uploader.uploadImage(uploadFilesBO.getFile(), uploadFilesBO.getTargetPath());
            } catch (IOException e) {
                throw new BusinessException(10012, String.format("文件上传失败: %s", e.getMessage()));
            }
        }
    }

    /**
     * 构建问题实体并保存到数据库
     *
     * @param uploadFilesBOList 包含图片信息的UploadFilesBO列表
     * @param creatorName       创建者姓名
     * @param creatorAccountId  创建者账号ID
     * @param creatorDept       创建者部门
     * @param questionContent   问题内容
     * @param questionType      问题类型
     * @throws BusinessException 当数据库操作失败时抛出
     */
    private void saveQuestionEntity(List<UploadFilesBO> uploadFilesBOList, String creatorName,
                                    String creatorAccountId, String creatorDept,
                                    String questionContent, String questionType) {
        String imagePaths = uploadFilesBOList.stream()
                .map(UploadFilesBO::getFileName)
                .collect(Collectors.joining(","));

        UserQuestionsEntity userQuestionsEntity = UserQuestionsEntity.builder()
                .creatorName(creatorName)
                .creatorAccountId(creatorAccountId)
                .creatorDept(creatorDept)
                .questionContent(questionContent)
                .questionType(questionType)
                .filePaths(imagePaths)
                .build();

        try {
            userQuestionsMapper.insert(userQuestionsEntity);
        } catch (Exception e) {
            throw new BusinessException(10013, String.format("问题保存失败: %s", e.getMessage()));
        }
    }
}
